package com.qst.order.listener;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.qst.order.config.RabbitMQConfig;
import com.qst.order.domain.MessageTransaction;
import com.qst.order.domain.Order;
import com.qst.order.mapper.MessageTransactionMapper;
import com.qst.order.mapper.OrderMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.util.Date;

@Component
@Slf4j
@RequiredArgsConstructor
public class OrderRabbitListen {

    private final OrderMapper orderMapper;


    private final MessageTransactionMapper messageTransactionMapper;

    // 监听延迟队列，处理订单超时逻辑
    @RabbitListener(queues = RabbitMQConfig.DELAYED_QUEUE)
    @Transactional(rollbackFor = Exception.class) // 确保订单更新和事务表更新原子性
    public void orderPayQueue(Message message) {
        // 1. 解析消息：从消息头获取messageId，从消息体获取订单ID
        String messageId = message.getMessageProperties().getHeader("messageId");
        String orderId = new String(message.getBody(), StandardCharsets.UTF_8); // 消息体为订单ID

        // 2. 校验消息合法性（本地事务表中必须存在该消息记录）
        MessageTransaction msgTx = messageTransactionMapper.selectOne(
                new QueryWrapper<MessageTransaction>().eq("message_id", messageId)
        );
        if (msgTx == null) {
            log.error("消息不存在，可能已被清理或非法消息：messageId={}, orderId={}", messageId, orderId);
            return;
        }

        // 3. 幂等性处理：若已处理成功，直接返回（避免重复消费）
        if (msgTx.getHandleStatus() == 2) { // 2-已处理
            log.info("消息已处理，无需重复操作：messageId={}, orderId={}", messageId, orderId);
            return;
        }

        // 4. 更新状态为“处理中”（防止并发处理）
        MessageTransaction updateTx = new MessageTransaction();
        updateTx.setHandleStatus(1); // 1-处理中
        updateTx.setHandleCount(msgTx.getHandleCount() + 1); // 处理次数+1
        messageTransactionMapper.update(
                updateTx,
                new UpdateWrapper<MessageTransaction>().eq("message_id", messageId)
        );

        try {
            // 5. 核心业务：检查订单状态，未支付则取消
            Order order = orderMapper.selectById(orderId);
            if (order != null && "pending".equals(order.getStatus())) {
                UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
                updateWrapper.set("status", "canceled").eq("order_id", orderId);
                orderMapper.update(updateWrapper);
                log.info("订单超时取消成功：orderId={}, messageId={}", orderId, messageId);
            } else {
                log.info("订单无需处理（已支付或不存在）：orderId={}, messageId={}", orderId, messageId);
            }

            // 6. 处理成功：更新状态为“已处理”，记录处理时间
            updateTx = new MessageTransaction();
            updateTx.setHandleStatus(2); // 2-已处理
            updateTx.setHandleTime(new Date());
            messageTransactionMapper.update(
                    updateTx,
                    new UpdateWrapper<MessageTransaction>().eq("message_id", messageId)
            );

        } catch (Exception e) {
            // 7. 处理失败：更新状态为“处理失败”，记录异常信息
            updateTx = new MessageTransaction();
            updateTx.setHandleStatus(3); // 3-处理失败
            updateTx.setRemark("订单处理失败：" + e.getMessage());
            messageTransactionMapper.update(
                    updateTx,
                    new UpdateWrapper<MessageTransaction>().eq("message_id", messageId)
            );
            log.error("订单处理失败：orderId={}, messageId={}", orderId, messageId, e);
            // 若需要重试，可抛出AmqpRejectAndDontRequeueException（结合RabbitMQ重试机制）
            throw new AmqpRejectAndDontRequeueException("处理失败，触发重试", e);
        }
    }
}
